﻿using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using NoSqlTest.Dto;
using NoSqlTest.EfContext;
using NoSqlTest.Model;
using NoSqlTest.ViewModel;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace NoSqlTest.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class EfCoreController : ControllerBase
    {
        private readonly ILogger<EfCoreController> _logger;
        private readonly IDbContextFactory _efDbContext;
        public EfCoreController(ILogger<EfCoreController> logger, IDbContextFactory efDbContext)
        {
            this._logger = logger;
            this._efDbContext = efDbContext;
        }
        /// <summary>
        /// 添加班级
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        [HttpPost("AddClass/{name}")]
        public IActionResult AddClass(string name)
        {
            var db = _efDbContext.ConnWriteOrRead(WriteAndReadEnum.Write);
            ClassGrade classGrade = new ClassGrade { Name = name };
            db.Add(classGrade);
            db.SaveChanges();
            return Ok(classGrade.Id);
        }
        /// <summary>
        /// 添加课程和老师
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        [HttpPost("AddCourse/{name}")]
        public IActionResult AddCourse(string name)
        {
            var db = _efDbContext.ConnWriteOrRead(WriteAndReadEnum.Write);
            Course classGrade = new Course { Name = name, Teacher = name + "老师" };
            db.Add(classGrade);
            db.SaveChanges();
            return Ok(classGrade.Id);
        }
        /// <summary>
        /// 给班级添加课程
        /// </summary>
        /// <param name="classAddCourse"></param>
        /// <returns></returns>
        [HttpPost("ClassAddCourse")]
        public IActionResult ClassAddCourse([FromBody] ClassAddCourse classAddCourse)
        {
            var db = _efDbContext.ConnWriteOrRead(WriteAndReadEnum.Write);
            var date = db.Classs.Include(t => t.Classs)
                .Where(t => t.Id == classAddCourse.ClassId).First();
            foreach (var i in classAddCourse.CourseIds)
            {
                if (!date.Classs.Select(t => t.Id).Contains(i))
                {
                    date.Classs.Add(new MiddleClassCourse
                    {
                        ClassId = date.Id,
                        CourseId = i
                    });
                }
            }
            return Ok(db.SaveChanges());
        }
        /// <summary>
        /// 插入学生
        /// </summary>
        /// <param name="student"></param>
        /// <returns></returns>
        [HttpPost("AddStudent")]
        public IActionResult AddStudent([FromBody] AddStudent student)
        {
            try
            {
                StringBuilder str = new StringBuilder();
                Stopwatch stopwatch2 = new Stopwatch();
                stopwatch2.Start();
                var db = _efDbContext.ConnWriteOrRead(WriteAndReadEnum.Write);
                List<Student> Students11 = new List<Student>();
                for (int i = 0; i < student.Count; i++)
                {
                    Students11.Add(new Student
                    {
                        ClassId = student.ClassId,
                        Name = student.Count.ToString(),
                        Age = 20,
                        Sex = 1,
                    });
                }
                db.Students.AddRange(Students11);
                db.SaveChanges();
                stopwatch2.Stop();
                str.Append($"DbContext插入{student.Count}条数据耗时：" + stopwatch2.ElapsedMilliseconds.ToString());

                _logger.LogInformation(str.ToString());
                return Ok(str.ToString());
            }
            catch (Exception ex)
            {
                return Ok(ex.Message);
            }
        }
        /// <summary>
        /// 插入学生-带选修课程
        /// </summary>
        /// <param name="course"></param>
        /// <returns></returns>
        [HttpPost("AddStudentCourse")]
        public IActionResult AddStudentCourse([FromBody] AddStudentCourse course)
        {
            try
            {
                StringBuilder str = new StringBuilder();
                Stopwatch stopwatch1 = new Stopwatch();
                stopwatch1.Start();
                var db = _efDbContext.ConnWriteOrRead(WriteAndReadEnum.Write);
                for (int i = 0; i < course.StudentCount; i++)
                {
                    db.Students.Add(new Student
                    {
                        ClassId = course.ClassId,
                        Name = i.ToString(),
                        Age = 22,
                        Sex = 0,
                        Courses = new List<MiddleStudentCourse> { new MiddleStudentCourse { CourseId = course.CourseId } }
                    });
                }
                db.SaveChanges();
                stopwatch1.Stop();
                str.Append($"方法1插入{course.StudentCount * 2}条数据耗时：" + stopwatch1.ElapsedMilliseconds.ToString());

                _logger.LogInformation(str.ToString());
                return Ok(str.ToString());
            }
            catch (Exception ex)
            {
                return Ok(ex.Message);
            }
        }
        /// <summary>
        /// 查询学生
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [HttpGet("GetStudent/{id}")]
        public IActionResult GetStudent(int id)
        {
            try
            {
                StringBuilder str = new StringBuilder();
                Stopwatch stopwatch1 = new Stopwatch();
                stopwatch1.Start();
                var db = _efDbContext.ConnWriteOrRead(WriteAndReadEnum.Read);
                var student1 = db.Students
                    .Include(a => a.Class)
                    .Include(a => a.Courses).ThenInclude(t => t.Course)
                    .Where(a => a.Id == id)
                    .Select(a => new StudentDto
                    {
                        ClassName = a.Class.Name,
                        //CourseIds = a.Courses.Select(t => t.CourseId).ToList(),
                        //Courses = a.Courses.Select(t => t.Course).ToList()
                    }).AsNoTracking()
                    .First();

                stopwatch1.Stop();
                str.Append($"查询数据耗时：" + stopwatch1.ElapsedMilliseconds.ToString());

                _logger.LogInformation(str.ToString());
                return Ok(student1);
            }
            catch (Exception ex)
            {
                return Ok(ex.Message);
            }
        }
        /// <summary>
        /// 查询班级中的所有学生
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [HttpGet("GetClassStudent/{id}")]
        public IActionResult GetClassStudent(int id)
        {
            try
            {
                StringBuilder str = new StringBuilder();
                Stopwatch stopwatch2 = new Stopwatch();
                stopwatch2.Start();
                var db = _efDbContext.ConnWriteOrRead(WriteAndReadEnum.Read);
                var students = db.Classs
                    .Include(a => a.Students)
                    .Where(a => a.Id == id)
                    .AsNoTracking()
                    .First();
                stopwatch2.Stop();
                str.Append($"查询数据耗时：" + stopwatch2.ElapsedMilliseconds.ToString());

                _logger.LogInformation(str.ToString());
                return Ok(str.ToString());
            }
            catch (Exception ex)
            {
                return Ok(ex.Message);
            }
        }
        /// <summary>
        /// 查询学生的所有课程
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [HttpGet("GetStudentCourse/{id}")]
        public IActionResult GetStudentCourse(int id)
        {
            try
            {
                StringBuilder str = new StringBuilder();
                Stopwatch stopwatch1 = new Stopwatch();
                stopwatch1.Start();
                var db = _efDbContext.ConnWriteOrRead(WriteAndReadEnum.Read);
                var student = db.Students
                    .Where(t => t.Id == id).First();

                var item1 = (from a in db.Set<MiddleClassCourse>()
                            join b in db.Set<Course>() on a.CourseId equals b.Id
                            select new {a.ClassId, b.Id,b.Name})
                            .Where(t => t.ClassId == student.ClassId)
                            .Select(a => new { a.Id,a.Name})
                            .ToList();

                var item2 = (from a in db.Set<MiddleStudentCourse>()
                            join b in db.Set<Course>() on a.CourseId equals b.Id
                            select new {a.StudentId, b.Id, b.Name })
                            .Where(t => t.StudentId == id)
                            .Select(a => new { a.Id, a.Name })
                            .ToList();

                item1.AddRange(item2);
                stopwatch1.Stop();
                str.Append($"查询数据耗时：" + stopwatch1.ElapsedMilliseconds.ToString());

                _logger.LogInformation(str.ToString());
                return Ok(str.ToString());
            }
            catch (Exception ex)
            {
                return Ok(ex.Message);
            }
        }
        /// <summary>
        /// 修改学生名
        /// </summary>
        /// <param name="student"></param>
        /// <returns></returns>
        [HttpPost("UpdateStudent")]
        public IActionResult UpdateStudent([FromBody] UpdateStudent student)
        {
            try
            {
                StringBuilder str = new StringBuilder();
                Stopwatch stopwatch1 = new Stopwatch();
                stopwatch1.Start();
                var db = _efDbContext.ConnWriteOrRead(WriteAndReadEnum.Write);
                var date = new Student { Id = student.Id, Age = student.Age, Sex = student.Sex, Name = student.Name };
                db.Students.Attach(date);
                db.Entry(date).Property(p => p.Name).IsModified = true;
                db.Entry(date).Property(p => p.Sex).IsModified = true;
                db.Entry(date).Property(p => p.Age).IsModified = true;
                db.SaveChanges();
                stopwatch1.Stop();
                str.Append($"指定列修改数据耗时：" + stopwatch1.ElapsedMilliseconds.ToString());

                //Stopwatch stopwatch3 = new Stopwatch();
                //stopwatch3.Start();
                //var db = _efDbContext.ConnWriteOrRead(WriteAndReadEnum.Write);
                //var date = db.Students.Where(a => a.Id == student.Id).First();
                //date.Name = student.Name;
                //date.Sex = student.Sex;
                //date.Age = student.Age;
                //db.SaveChanges();
                //stopwatch3.Stop();
                //str.AppendLine($"DbContext修改数据耗时：" + stopwatch3.ElapsedMilliseconds.ToString());


                //方法3：使用EntityFrameworkCore.Extensions
                _logger.LogInformation(str.ToString());
                return Ok(str.ToString());
            }
            catch (Exception ex)
            {
                return Ok(ex.Message);
            }
        }
    }
}
